package flatlandAgent;

import javax.swing.JPanel;

public class FlatlandGame implements FlatlandModel{
	
	private FlatlandMap map; 
	private int posX; 
	private int posY; 
	
	private int priviusPosX; 
	private int priviusPosY;
	
	private char heading; 
	private boolean draw = false; 
	private FlatlandPanel panel; 
	
	public enum Direction{
		UP	(0,-1,'u'),
		RIGHT	(1,0,'r'),
		DOWN 	(0,1,'d'),
		LEFT	(-1,0,'l'); 
		
		private int deltaX; 
		private int deltaY; 
		private char dir; 
		Direction(int deltaX, int deltaY, char dir){
			this.setDeltaX(deltaX); 
			this.setDeltaY(deltaY);
			this.setCharDir(dir);
		}
		
		private void setDeltaY(int deltaY) {
			this.deltaY = deltaY;
		}
		private void setDeltaX(int deltaX) {
			this.deltaX = deltaX;
		}
		private void setCharDir(char dir) {
			this.dir = dir; 
		}

		public int getDeltaY() {
			return deltaY;
		}
		public int getDeltaX() {
			return deltaX;
		}
		public char getCharDir(){
			return dir; 
		}
		
		
		public Direction leftDirection(){
			switch (this) {
			case UP:
				return LEFT; 
			case RIGHT:
				return UP; 
			case DOWN:
				return RIGHT; 
			case LEFT:
				return DOWN;
			}
			return null; 
		}
		
		public Direction rightDirection(){
			switch (this) {
			case UP:
				return RIGHT; 
			case RIGHT:
				return DOWN; 
			case DOWN:
				return LEFT; 
			case LEFT:
				return UP;
			}
			return null; 
		}
		
		public Direction forwardDirection(){
			return this; 
		}
		
		public static Direction getDirection(char dir){
			switch (dir) {
			case 'u':
				return UP;
			case 'r':
				return RIGHT; 
			case 'd':
				return DOWN; 
			case 'l':
				return LEFT; 
			}
			return null; 
		}
		
		public String toString(){
			return "Delta x: "+deltaX+"   Delta y: "+deltaY; 
		}
	}
	
	
	public FlatlandGame(FlatlandMap map){
		this.map = map.copy(); 
		posX = 0; 
		posY = 0; 
		heading = 'd'; 
		clearPosition(); 
	}
	
	
	public boolean[] getFoodSensors(){
		char[] sensors = getSensors(); 
		boolean[] foodSensors = new boolean[sensors.length]; 
		for (int i = 0; i < sensors.length; i++) {
			foodSensors[i] = sensors[i] == 'f'; 
		}
		return foodSensors;
	}
	
	public boolean[] getPoisonSensors(){
		char[] sensors = getSensors(); 
		boolean[] poisonSensors = new boolean[sensors.length]; 
		for (int i = 0; i < sensors.length; i++) {
			poisonSensors[i] = sensors[i] == 'p'; 
		}
		return poisonSensors; 
	}
	
	private char[] getSensors(){
		char[] sensors = new char[3]; 
		sensors[0] = getLeft(); 
		sensors[1] = getFront(); 
		sensors[2] = getRight();
		return sensors; 
	}
	
	private char getLeft(){
		Direction dir = Direction.getDirection(heading).leftDirection();
		return map.getCell(posX + dir.getDeltaX(), posY + dir.getDeltaY()); 
	}
	
	private char getFront(){
		Direction dir = Direction.getDirection(heading); 
		return map.getCell(posX + dir.getDeltaX(), posY + dir.getDeltaY());
	}
	
	private char getRight(){
		Direction dir = Direction.getDirection(heading).rightDirection(); 
		return map.getCell(posX + dir.getDeltaX(), posY + dir.getDeltaY());
	}
	
	@Override
	public int move(Action action) {
		switch (action) {
		case MOVE_LEFT:
			moveLeft();
			break;
		case MOVE_FORWARD:
			moveForward();
			break;
		case MOVE_RIGHT:
			moveRight();
			break;
		} 

		posX = modulus(posX,this.getMapDimention()); 
		posY = modulus(posY,this.getMapDimention());  
		
		if (draw){
			panel.drawGame();
		}
		return clearPosition(); 
	}
	
	public void setDraw(boolean draw){
		this.draw = draw; 
		if (draw){
			panel = new FlatlandPanel(this);
		}
	}
	
//	private void printSensors() {
//		char[] sensors = getSensors(); 
//		for (char c : sensors){
//			System.out.print(c + ", ");
//		}
//		System.out.println();
//	}

	private int clearPosition(){
		int returnValue = 0; 
		if (map.getCell(posX, posY) == 'f'){
			returnValue = 1; 
		} else if (map.getCell(posX, posY) == 'p'){
			returnValue = -1; 
		}
		map.setCell(posX, posY, '.'); 
		return returnValue; 
	}
	
	private static int modulus(int a, int b){
		while (a < 0) a += b;
		return a%b;
	}

	private void moveLeft(){
		Direction dir = Direction.getDirection(heading).leftDirection();
		posX += dir.deltaX; 
		posY += dir.deltaY; 
		heading = dir.getCharDir(); 
	}
	
	private void moveForward(){
		Direction dir = Direction.getDirection(heading); 
		//System.out.println(dir);
		posX += dir.deltaX; 
		posY += dir.deltaY; 
		heading = dir.getCharDir(); 
	}
	
	private void moveRight(){
		Direction dir = Direction.getDirection(heading).rightDirection(); 
		posX += dir.deltaX; 
		posY += dir.deltaY; 
		heading = dir.getCharDir(); 
	}

	@Override
	public JPanel getGamePanel() {
		if (panel == null){
			return new JPanel(); 
		}
		return panel;
	}


	@Override
	public char getCell(int x, int y) {
		return map.getCell(x, y);
	}


	@Override
	public int getMapDimention() {
		return map.getSize();
	}


	@Override
	public int getPosX() {
		return posX;
	}


	@Override
	public int getPosY() {
		return posY;
	}
	
	@Override
	public int getPreviusPosX() {
		return priviusPosX;
	}


	@Override
	public int getPreviusPosY() {
		return priviusPosY;
	}


	@Override
	public char getHeading() {
		return heading;
	}
	
	public String toString(){
		String theString = ""; 
		theString += "PosX: " + posX + "   PosY: " + posY + "   Heading: " + heading + "\n"; 
		return theString + map.toString();
	}
}
